
import IpcParams from "../IpcParams";
import { createAgent } from './utils';
import Axios from 'axios';
import axiosRetry from 'axios-retry';

export default class BlumGame {
  constructor(tokenInfo) {
    this.tokenInfo = tokenInfo
    const agent = createAgent(this.tokenInfo.proxy)
    const headers = {
      "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
    }
    this.axios = Axios.create({
      headers: headers,
      httpAgent: agent,
      httpsAgent: agent,
    })
    axiosRetry(this.axios, {
      retries: 3, retryDelay: (retryCount) => {
        return 2000
      }
    });
  }

  random_str(length) {
    var str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var result = '';
    for (var i = length; i > 0; --i)
      result += str[Math.floor(Math.random() * str.length)];
    return result;
  }

  getRandomIntInclusive(min, max) {
    const minCeiled = Math.ceil(min);
    const maxFloored = Math.floor(max);
    return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled); // 包含最小值和最大值
  }

  getAnswerByQuestion(question) {

    // Ton voices live                I LOVE BLUM
    // What's DAO?                    N/A
    // How to Analyze Crypto?:        VALUE
    // Forks Explained:               GO GET
    // Secure your Crypto!:           BEST PROJECT EVER
    // Navigating Crypto:             HEYBLUM
    // What are Telegram Mini Apps?:  CRYPTOBLUM 
    // Liquidity Pools Guide          BLUMERSSS
    // Say no to rug pull!            SUPERBLUM
    // What are AMMs                  CRYPTOSMART

    if (question.indexOf('voices') > 0) {
      return 'I LOVE BLUM'
    } else if (question.indexOf('DAO') > 0) {
      return 'مشاهدة فقط'
    } else if (question.indexOf('Analyze') > 0) {
      return 'VALUE'
    } else if (question.indexOf('Explained') > 0) {
      return 'GO GET'
    } else if (question.indexOf('ecure') > 0) {
      return 'BEST PROJECT EVER'
    } else if (question.indexOf('vigating') > 0) {
      return 'HEYBLUM'
    } else if (question.indexOf('Mini') > 0) {
      return 'CRYPTOBLUM'
    } else if (question.indexOf('quidity') > 0) {
      return 'BLUMERSSS'
    } else if (question.indexOf('Rug') > 0) {
      return 'SUPERBLUM'
    } else if (question.indexOf('AMMs') > 0) {
      return 'CRYPTOSMART'
    } else if (question.indexOf('2.5M') > 0) {
      return 'happydogs'
    } else if (question.indexOf('oxxing') > 0) {
      return 'nodoxxing'
    } else if (question.indexOf('re-Market') > 0) {
      return 'wowblum'
    } else if (question.indexOf('lay track') > 0) {
      return 'blum - big city life'
    } else if (question.indexOf('emecoi') > 0) {
      return 'memeblum'
    } else if (question.indexOf('Burning') > 0) {
      return 'onfire'
    } else if (question.indexOf('Rainbow') > 0) {
      return 'soblum'
    } else if (question.indexOf('Part 1') > 0) {
      return 'blumexplorer'
    } else {
      return ''
    }
  }

  async run() {
    try {
      const axios = this.axios
      let webSessionUrl = this.tokenInfo.tgweb

      // if ( this.tokenInfo.phone == '0017143529996' || this.tokenInfo.phone == '008615390068850') {
      //   console.log('==================================== ', this.tokenInfo.phone)
      // } else {
      //   console.log('=??????????????????????????????????= ', this.tokenInfo.phone)
      //   return
      // }

      if (webSessionUrl.startsWith("https://") == false) {
        console.error(`${this.tokenInfo.phone}  error session url ${webSessionUrl}`);
        return
      }

      webSessionUrl = decodeURIComponent(webSessionUrl)
      let session = webSessionUrl.split("#tgWebAppData=")[1]
      session = session.split("&tgWebAppVersion")[0]

      // if ( session.indexOf('username') <= 0) { // At the first time, we need check if the user registed. If the URL value has not inclulded username value, it means the current account has not registed. Need register first. 
      let user_name = session.slice(session.indexOf('first_name') + 19, session.indexOf('last_name') - 9)
      // user_name = user_name.replace(/[\@\#\$\%\^\&\*\{\}\:\"\L\<\>\?]/, '')
      user_name = user_name.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
      user_name = user_name + this.random_str(8)
      const register_user_payload = {
        'query': session,
        'username': user_name
      }

      const req_header = {
        'content-type': 'application/json',
      }
      const inviteUrl = this.tokenInfo.inviteUrl
      let refId = null
      if (inviteUrl != null) {
        refId = inviteUrl.split("startapp=")[1]
        refId = refId.split("_")[1]
      }
      // console.log("邀请码", refId)
      // Try to register, if already registed will got code 500 and an error message. But just ignore it currently.
      await axios.post('https://user-domain.blum.codes/api/v1/auth/provider/PROVIDER_TELEGRAM_MINI_APP', register_user_payload, {
        headers: {
          'content-type': 'application/json'
        },
        data: {
          "referralToken": refId,
        }
      })
        .then(response => {

        })
        .catch(function (error) {
          if (error.response.data.message != null && error.response.data.message.indexOf('is already connected to another user') > 0) {
            console.log('The account already registed.')
          }
        })

      // Get TOKEN and update DB
      const get_token_payload = {
        'query': session,
        "referralToken": refId,
      }


      const get_token_rep = await this.axios.request("https://user-domain.blum.codes/api/v1/auth/provider/PROVIDER_TELEGRAM_MINI_APP", {
        method: "post",
        headers: req_header,
        data: get_token_payload
      })

      // console.log('get_token_rep : ', get_token_rep)

      const authed_header = {
        authorization: "Bearer " + get_token_rep.data.token.access
      }

      /* start works */

      /* 0. check wallet */
      console.log('-----------------------------------------------------retrieve  ----====  wallet response')

      await axios.get('https://wallet-domain.blum.codes/api/v1/wallet/my/balance?fiat=usd', {
        headers: authed_header
      }).then(response => {
        console.log('-----------------------------------------------------wallet response')
        console.log(response)
      }).catch(function (error) {
        console.log('-----------------------------------------------------error  response')
        console.log(error)
      })


      /* 1. Daily reward */
      await axios.get('https://game-domain.blum.codes/api/v1/daily-reward?offset=-480', {
        headers: authed_header
      }).then(response => {
        // console.log(response)
      }).catch(function (error) {
        // console.log(error)
      })

      /* 2. Daily Check in */
      await axios.post('https://game-domain.blum.codes/api/v1/daily-reward?offset=-480', '', {
        headers: authed_header
      }).then(response => {
      }).catch(function (error) {
      })

      const sleepNow = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

      let playPasses = 0;
      /* 3. Start farm */
      await axios.post('https://game-domain.blum.codes/api/v1/farming/start', '', {
        headers: authed_header
      }).then(response => {
      }).catch(function (error) {
      })

      /* 4. User balance */
      await axios.get('https://game-domain.blum.codes/api/v1/user/balance', {
        headers: authed_header
      }).then(response => {
        // console.log('Current user balance is : ', response.data)
        playPasses = response.data.playPasses
        const timestamp = response.data.timestamp
        const endTime = response.data.farming.endTime

        if ((timestamp - endTime) > 0) {
          // Claim farming
          // console.log('Claim farming')
          // https://game-domain.blum.codes/api/v1/farming/claim
          axios.post('https://game-domain.blum.codes/api/v1/farming/claim', '', {
            headers: authed_header
          }).then(response => {
          }).catch(function (error) {
          })

        } else {
        }
      }).catch(function (error) {
        // console.log(error)
      })

      /* 5. Play games */
      // console.log('playPasses : ------------? ', playPasses)
      for (let i = 0; i < playPasses; i++) {

        var d1 = new Date();

        const sleepMillisecond = 40000 + this.getRandomIntInclusive(10000, 30000)
        // console.log('Waiting : ', sleepMillisecond)

        // Start game and get gameId
        let currentGameId = ''
        await axios.post('https://game-domain.blum.codes/api/v1/game/play', '', {
          headers: authed_header
        }).then(response => {
          currentGameId = response.data.gameId
        }).catch(function (error) {
          // console.log(error)
        })

        await sleepNow(sleepMillisecond)
        var d2 = new Date();
        // console.log(parseInt(d2 - d1) / 1000);//两个时间相差的秒数
        const game_score = this.getRandomIntInclusive(180, 199)

        // after waiting about 60 seconds, we can claim game score.
        const game_result = {
          "gameId": currentGameId,
          "points": game_score
        }

        // console.log('Claim game data: ', game_result)
        await axios.post('https://game-domain.blum.codes/api/v1/game/claim', game_result, {
          headers: authed_header
        }).then(response => {
          currentGameId = response.data.gameId
        }).catch(function (error) {
          // console.log(error)
        })

      }

      /* Start tasks */
      let task_objects = [];
      await axios.get('https://earn-domain.blum.codes/api/v1/tasks', {
        headers: authed_header
      }).then(response => {
        response.data.forEach((value, key) => {
          // console.log(' =====> : Tasks')
          // console.log(value)
          if (value.title == 'Weekly') {
            // console.log(' =====> : Weekly')
            value.tasks.forEach((weeklyValue, weeklyKey) => {
              if (weeklyValue.status != 'FINISHED' && weeklyValue.isHidden != true) {
                task_objects.push(weeklyValue)
              }
              weeklyValue.subTasks.forEach((weeklySubValue, weeklyKey) => {
                if (weeklySubValue.status != 'FINISHED' && weeklySubValue.isHidden != true) {
                  task_objects.push(weeklySubValue)
                }
              })
            })

          } else if (value.title == 'Promo') {
            value.tasks.forEach((promoValue, promolyKey) => {
              if (promoValue.status != 'FINISHED' && promoValue.isHidden != true) {
                task_objects.push(promoValue)
              }
              promoValue.subTasks.forEach((promoSubValue, weeklyKey) => {
                if (promoSubValue.status != 'FINISHED' && promoSubValue.isHidden != true) {
                  task_objects.push(promoSubValue)
                }
              })
            })
          } else {
            value.subSections.forEach((subSectionsValue, subSectionsKey) => {
              subSectionsValue.tasks.forEach((ssValue, ssKey) => {
                if (ssValue.status != 'FINISHED' && ssValue.isHidden != true) {
                  task_objects.push(ssValue)
                }
              })
            })
          }
        })
      }).catch(function (error) {
        // console.log(error)
      })

      // console.log("---------------------------------------------------------- task_objects : ", task_objects)

      for (let i = 0; i < task_objects.length; i++) {
        const task_temp = task_objects[i]
        // console.log("task claim", task_temp)
        // https://earn-domain.blum.codes/api/v1/tasks/f83c525c-9844-469b-a104-817814f337e7/start

        if (task_temp.status != 'READY_FOR_CLAIM') {    // Start task     
          // start firstly
          axios.post('https://earn-domain.blum.codes/api/v1/tasks/' + task_temp.id + '/start', '', {
            headers: authed_header
          }).then(response => {
            // console.log("task begin response", response.data)
          }).catch(function (error) {

          })
          // sleep while
          await sleepNow(3333)

          if (task_temp.validationType == 'KEYWORD') { // need validate
            // validate question 

            const keyword = this.getAnswerByQuestion(task_temp.title)
            // console.log('keyword =========================    ', keyword)

            if (keyword != '') {
              const answer_body = {
                "keyword": keyword
              }

              axios.post('https://earn-domain.blum.codes/api/v1/tasks/' + task_temp.id + '/validate', answer_body, {
                headers: authed_header
              }).then(response => {

              }).catch(function (error) {
                console.log('----- Question answer ERROR -----')
                console.log(error)
              })
            } else {
              console.log('not found question for  ---->>> ', task_temp.title)
            }
          }
        } else { // READY_FOR_CLAIM
          axios.post('https://earn-domain.blum.codes/api/v1/tasks/' + task_temp.id + '/claim', '', {
            headers: authed_header
          }).then(response => {
            // console.log("task claim response", response.data)
          }).catch(function (error) {
            // console.log(error)
          })
        }
        await sleepNow(1340)
      }

      /* 4. User balance */
      await axios.get('https://game-domain.blum.codes/api/v1/user/balance', {
        headers: authed_header
      }).then(response => {
        const availableBalance = response.data.availableBalance
        this.availableBalance = response.data.availableBalance
        const timestamp = response.data.timestamp
        const endTime = response.data.farming.endTime

        if ((timestamp - endTime) > 0) {
          // Claim farming
          console.log('Claim farming')
          // https://game-domain.blum.codes/api/v1/farming/claim
          axios.post('https://game-domain.blum.codes/api/v1/farming/claim', '', {
            headers: authed_header
          }).then(response => {
            // console.log(response)
          }).catch(function (error) {
            // console.log(error)
          })

        } else {
          console.log('The claim remain : ', timestamp - endTime)
        }
      }).catch(function (error) {
        // console.log(error)
      })

      this.tokenInfo.score = this.availableBalance
      this.tokenInfo.gameupdate = (new Date()).toLocaleString()
      this.tokenInfo.count = (this.tokenInfo.count || 0) + 1
      console.log(Date().toLocaleString(), "blum end", this.tokenInfo.phone, "score: ", this.tokenInfo.score)
      return new IpcParams("runBlum", this.tokenInfo)
    } catch (error) {
      console.log(Date().toLocaleString(), "blum error", this.tokenInfo.phone)
      // console.error(error)
      return new IpcParams("runBlum", this.tokenInfo, error)
    }
  }


}